package com.wz.jaav.classreader.classFile.attribute;

import com.wz.jaav.classreader.ClassReader;
import com.wz.jaav.instruction.Interpreter;
import com.wz.jaav.util.CommonUtils;

import java.util.Arrays;

public class AttributeInfoCode extends AttributeInfo{
    private short maxStack;
    private short maxLocals;
    private int codeLength;
    private Code code;
    private short exceptionTableLength;
    private ExceptionInfo attributeInfoException;
    private short attributeCount;
    private Attribute[] attributes;

    public void build(byte[] attributeContent) {
        ClassReader cr = new ClassReader(attributeContent);
        byte[] ms = cr.doRead(2);
        short maxStack = CommonUtils.byteToShort(ms);
        this.maxStack = maxStack;
        byte[] ml = cr.doRead(2);
        short maxLocals = CommonUtils.byteToShort(ml);
        this.maxLocals = maxLocals;
        byte[] cl = cr.doRead(4);
        int codeLength = CommonUtils.bytes2Int(cl);
        this.codeLength = codeLength;
        byte[] code = cr.doRead(codeLength);
        System.out.println("        code:" + CommonUtils.bytesToHex(code));
        this.code = new Code(code);
        byte[] excpTablen = cr.doRead(2);
        short excpTablength = CommonUtils.byteToShort(excpTablen);
        System.out.println("        exception table length:" + excpTablength);
        this.exceptionTableLength = excpTablength;
        byte[] attriCount = cr.doRead(2);
        short attributeCount = CommonUtils.byteToShort(attriCount);
        this.attributeCount = attributeCount;
        System.out.println("        attributeCount:" + attributeCount);
        this.attributes = new Attribute[attributeCount];
        for (int i = 0; i < attributeCount; i++ ){
            Attribute attribute = new Attribute();
            attribute.build(cr);
            this.attributes[i] = attribute;
        }
    }

    public short getMaxStack() {
        return maxStack;
    }

    public short getMaxLocals() {
        return maxLocals;
    }

    public int getCodeLength() {
        return codeLength;
    }

    public Code getCode() {
        return code;
    }

    public Attribute[] getAttributes() {
        return attributes;
    }

    @Override
    public String toString() {
        return "AttributeInfoCode{" +
                "maxStack=" + maxStack +
                ", maxLocals=" + maxLocals +
                ", codeLength=" + codeLength +
                ", code=" + code +
                ", exceptionTableLength=" + exceptionTableLength +
                ", attributeInfoException=" + attributeInfoException +
                ", attributeCount=" + attributeCount +
                '}';
    }

    @Override
    public void printInfos(String placeholder) {
        System.out.println(placeholder + toString());
        if (attributes == null){
            return;
        }
        for (int i = 0; i < attributes.length; i++) {
            if (attributes[i] != null) {
                System.out.println(placeholder + "    Attribute In AttributeCode:" + (i + 1));
                attributes[i].printInfos("                ");
            }
        }
    }
}
